import * as THREE from 'three';
import { CollisionDetector, type CollisionResult } from './collisionDetector';
import { CollisionResponse, type ResponseConfig, type ResponseResult } from './collisionResponse';
import { CollisionDebugger, type DebugConfig, type CollisionStats } from './collisionDebugger';
import { CarController } from './carControls';

// 碰撞系统配置接口
export interface CollisionSystemConfig {
  enableCollision: boolean;
  showBoundingBoxes: boolean;
  showCollisionPoints: boolean;
  showCollisionNormals: boolean;
  showSpatialGrid: boolean;
  gridSize: number;
  responseStrength: number;
  bounceStrength: number;
  debugMode: boolean;
}

// 碰撞系统事件接口
export interface CollisionEvents {
  onCollisionStart?: (collisions: CollisionResult[]) => void;
  onCollisionEnd?: () => void;
  onCollisionUpdate?: (collisions: CollisionResult[], response: ResponseResult) => void;
}

/**
 * 碰撞系统主类
 * 整合碰撞检测、响应和调试功能
 */
export class CollisionSystem {
  private scene: THREE.Scene;
  private config: CollisionSystemConfig;
  private events: CollisionEvents;
  
  // 核心组件
  private detector: CollisionDetector;
  private response: CollisionResponse;
  private debugger: CollisionDebugger;
  
  // 状态管理
  private enabled: boolean = true;
  private wasColliding: boolean = false;
  private lastUpdateTime: number = 0;
  private updateInterval: number = 16; // 约60fps

  constructor(
    scene: THREE.Scene, 
    config: Partial<CollisionSystemConfig> = {},
    events: CollisionEvents = {}
  ) {
    this.scene = scene;
    this.events = events;
    
    // 默认配置
    this.config = {
      enableCollision: true,
      showBoundingBoxes: false,
      showCollisionPoints: true,
      showCollisionNormals: true,
      showSpatialGrid: false,
      gridSize: 10,
      responseStrength: 1.0,
      bounceStrength: 0.3,
      debugMode: false,
      ...config
    };

    // 初始化组件
    this.detector = new CollisionDetector(this.config.gridSize);
    
    this.response = new CollisionResponse({
      elasticity: this.config.bounceStrength,
      positionCorrectionStrength: this.config.responseStrength,
      friction: 0.8,
      velocityDamping: 0.3
    });
    
    this.debugger = new CollisionDebugger(scene, {
      showBoundingBoxes: this.config.showBoundingBoxes,
      showCollisionPoints: this.config.showCollisionPoints,
      showCollisionNormals: this.config.showCollisionNormals,
      showSpatialGrid: this.config.showSpatialGrid
    });

    this.enabled = this.config.enableCollision;
  }

  /**
   * 添加建筑物到碰撞系统
   * @param building 建筑物对象
   */
  public addBuilding(building: THREE.Object3D): void {
    this.detector.addBuilding(building);
  }

  /**
   * 移除建筑物从碰撞系统
   * @param building 建筑物对象
   */
  public removeBuilding(building: THREE.Object3D): void {
    this.detector.removeBuilding(building);
  }

  /**
   * 更新碰撞系统
   * @param carGroup 车辆组对象
   * @param carController 车辆控制器
   * @param deltaTime 时间增量
   * @returns 碰撞结果和响应信息
   */
  public update(
    carGroup: THREE.Group, 
    carController: CarController, 
    deltaTime: number
  ): { collisions: CollisionResult[]; response: ResponseResult } {
    const currentTime = Date.now();
    
    // 控制更新频率
    if (currentTime - this.lastUpdateTime < this.updateInterval) {
      return { 
        collisions: [], 
        response: {
          positionCorrected: false,
          velocityAdjusted: false,
          finalVelocity: carController.getCarState().speed,
          correctionDistance: 0
        }
      };
    }
    
    this.lastUpdateTime = currentTime;

    let collisions: CollisionResult[] = [];
    let response: ResponseResult = {
      positionCorrected: false,
      velocityAdjusted: false,
      finalVelocity: carController.getCarState().speed,
      correctionDistance: 0
    };

    if (this.enabled) {
      // 执行碰撞检测
      collisions = this.detector.checkCollisions(carGroup);
      
      // 处理碰撞响应
      if (collisions.length > 0) {
        response = this.response.resolveCollisions(carGroup, carController, collisions);
        
        // 触发碰撞开始事件
        if (!this.wasColliding) {
          this.events.onCollisionStart?.(collisions);
          this.wasColliding = true;
        }
        
        // 触发碰撞更新事件
        this.events.onCollisionUpdate?.(collisions, response);
      } else if (this.wasColliding) {
        // 触发碰撞结束事件
        this.events.onCollisionEnd?.();
        this.wasColliding = false;
      }
    }

    // 更新调试显示
    if (this.config.debugMode) {
      this.debugger.update(
        this.detector.getBuildingBounds(),
        this.detector.getCarBounds(),
        collisions,
        this.config.gridSize
      );
    }

    return { collisions, response };
  }

  /**
   * 启用或禁用碰撞检测
   * @param enabled 是否启用
   */
  public setEnabled(enabled: boolean): void {
    this.enabled = enabled;
    this.config.enableCollision = enabled;
  }

  /**
   * 检查是否启用
   * @returns 是否启用碰撞检测
   */
  public isEnabled(): boolean {
    return this.enabled;
  }

  /**
   * 设置调试模式
   * @param enabled 是否启用调试模式
   */
  public setDebugMode(enabled: boolean): void {
    this.config.debugMode = enabled;
    this.debugger.setVisible(enabled);
  }

  /**
   * 检查是否处于调试模式
   * @returns 是否处于调试模式
   */
  public isDebugMode(): boolean {
    return this.config.debugMode;
  }

  /**
   * 设置边界框显示
   * @param show 是否显示边界框
   */
  public setShowBoundingBoxes(show: boolean): void {
    this.config.showBoundingBoxes = show;
    this.debugger.updateConfig({ showBoundingBoxes: show });
  }

  /**
   * 设置碰撞点显示
   * @param show 是否显示碰撞点
   */
  public setShowCollisionPoints(show: boolean): void {
    this.config.showCollisionPoints = show;
    this.debugger.updateConfig({ showCollisionPoints: show });
  }

  /**
   * 设置碰撞法向量显示
   * @param show 是否显示碰撞法向量
   */
  public setShowCollisionNormals(show: boolean): void {
    this.config.showCollisionNormals = show;
    this.debugger.updateConfig({ showCollisionNormals: show });
  }

  /**
   * 设置空间网格显示
   * @param show 是否显示空间网格
   */
  public setShowSpatialGrid(show: boolean): void {
    this.config.showSpatialGrid = show;
    this.debugger.updateConfig({ showSpatialGrid: show });
  }

  /**
   * 设置响应强度
   * @param strength 响应强度 (0-2)
   */
  public setResponseStrength(strength: number): void {
    this.config.responseStrength = Math.max(0, Math.min(2, strength));
    this.response.updateConfig({ 
      positionCorrectionStrength: this.config.responseStrength 
    });
  }

  /**
   * 设置弹性强度
   * @param strength 弹性强度 (0-1)
   */
  public setBounceStrength(strength: number): void {
    this.config.bounceStrength = Math.max(0, Math.min(1, strength));
    this.response.updateConfig({ 
      elasticity: this.config.bounceStrength 
    });
  }

  /**
   * 设置摩擦系数
   * @param friction 摩擦系数 (0-1)
   */
  public setFriction(friction: number): void {
    this.response.updateConfig({ 
      friction: Math.max(0, Math.min(1, friction)) 
    });
  }

  /**
   * 更新配置
   * @param newConfig 新配置
   */
  public updateConfig(newConfig: Partial<CollisionSystemConfig>): void {
    this.config = { ...this.config, ...newConfig };
    
    // 更新子组件配置
    if (newConfig.responseStrength !== undefined) {
      this.setResponseStrength(newConfig.responseStrength);
    }
    
    if (newConfig.bounceStrength !== undefined) {
      this.setBounceStrength(newConfig.bounceStrength);
    }
    
    if (newConfig.enableCollision !== undefined) {
      this.setEnabled(newConfig.enableCollision);
    }
    
    if (newConfig.debugMode !== undefined) {
      this.setDebugMode(newConfig.debugMode);
    }
    
    // 更新调试器配置
    this.debugger.updateConfig({
      showBoundingBoxes: newConfig.showBoundingBoxes,
      showCollisionPoints: newConfig.showCollisionPoints,
      showCollisionNormals: newConfig.showCollisionNormals,
      showSpatialGrid: newConfig.showSpatialGrid
    });
  }

  /**
   * 获取当前配置
   * @returns 当前配置
   */
  public getConfig(): CollisionSystemConfig {
    return { ...this.config };
  }

  /**
   * 获取碰撞统计信息
   * @returns 统计信息
   */
  public getStats(): CollisionStats {
    return this.debugger.getStats();
  }

  /**
   * 重置统计信息
   */
  public resetStats(): void {
    this.debugger.resetStats();
  }

  /**
   * 获取响应配置
   * @returns 响应配置
   */
  public getResponseConfig(): ResponseConfig {
    return this.response.getConfig();
  }

  /**
   * 获取调试配置
   * @returns 调试配置
   */
  public getDebugConfig(): DebugConfig {
    return this.debugger.getConfig();
  }

  /**
   * 重置碰撞响应状态
   */
  public resetResponseState(): void {
    this.response.reset();
    this.wasColliding = false;
  }

  /**
   * 检查是否当前有碰撞
   * @returns 是否有碰撞
   */
  public hasActiveCollisions(): boolean {
    return this.wasColliding;
  }

  /**
   * 获取建筑物数量
   * @returns 注册的建筑物数量
   */
  public getBuildingCount(): number {
    return this.detector.getBuildingBounds().size;
  }

  /**
   * 设置更新间隔
   * @param interval 更新间隔（毫秒）
   */
  public setUpdateInterval(interval: number): void {
    this.updateInterval = Math.max(8, interval); // 最小8ms (约120fps)
  }

  /**
   * 清理资源
   */
  public dispose(): void {
    this.detector.dispose();
    this.debugger.dispose();
    
    // 清理事件监听器
    this.events = {};
    
    // 重置状态
    this.enabled = false;
    this.wasColliding = false;
  }
}